<?php
class LayoutManager
{
	private $_html_modes = array 
	(
		"XHTML-STRICT" => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n<html xmlns="http://www.w3.org/1999/xhtml" lang="%(lang)s" xml:lang="%(lang)s">',
		"XHTML-TRAN"   => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n<html xmlns="http://www.w3.org/1999/xhtml" lang="%(lang)s" xml:lang="%(lang)s">',
		"HTML4-STRICT" => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n<html lang="%(lang)s">',
		"HTML4-TRAN"   => '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n<html lang="%(lang)s">',
		"XHTML-11"     => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n<html lang="%(lang)s">',
		"HTML5"	       => '<!DOCTYPE html>\n<html lang="%(lang)s">',
	);

	public function __construct ( & $liwe )
	{
		$this->liwe = $liwe;

		$this->html_mode = "HTML5";

		// Language of the HTML page
		$this->lang = "en";

		$this->_page_dir = $this->liwe->cfg->get ( "PAGES_DIR", "./pages" );

		$this->_re = array (
			"spaces" => "[\n\r\t]",
			"body"   => ".*<body[^>]*>(.*)<\/body>.*",
			"rep"    => "<!-- {{{ REP: (?P<nome>[^ ]*) (.*) -->.*<!-- }}} (?P=nome) -->",
			"comments" => "<!--.*?-->",
			"commands" => ".*?\"|\'.*?\')|\W" );

		$this->_css = array ();
		$this->_js  = array ();
	
		$this->_css_nocache = array ();
		$this->_js_nocache  = array ();

		$this->_js_code = array ();
		$this->_js_code_tail = array ();
		$this->_links = array ();

		$this->_cache_dir = null;
		$this->_site_version = $this->liwe->cfg->get ( "SITE_VERSION", "1" );

		$this->title = $this->liwe->cfg->get ( "TITLE", "" );

		$this->metas = array ( "resource-type" => "document" );

		$this->_body_classes = array ();
		// $this->_chrome_frame ();
		$this->_enable_cache ();

		$this->_has_redir = false;
	}

	
	public function redirect ( $url )
	{
		$this->_has_redir = true;

		/* FIXME: finire
		self.liwe.pyhp.set_header (  'Location', url )
		self.liwe.pyhp.return_code = "301 Moved Permanently"
		*/
	}

	private function _enable_cache ()
	{
		$cdir = $this->liwe->cfg->get ( "LIWE_CACHE_DIR" );

		if ( ! $cdir ) return;
		if ( $this->liwe->cfg-get ( "DEBUG", "0" ) != 0 ) return;

		$this->_set_cache ( $cdir );
	}

	public function set_meta ( $name, $value )
	{
		$this->_metas [ strtolower ( $name ) ] = $value;
	}

	private function dump_metas ()
	{
		foreach ( $this->_metas as $k => $v )
		{
			if ( ! $v ) continue;

			$v = str_replace ( array ( "\n", "\r" ), " ", str_replace ( '"', "'", $v ) );

			print '<meta name="$k" content="$v" />';

		}
	}

	private function _set_cache ( $dir_name )
	{
		$this->_cache_dir = $dir_name;
	}

	public function add_link ( $rel, $type, $href, $title )
	{
		$this->_links [] = array ( "rel" => $rel, "type" => $type, "title" => $title, "href" => $href );
	}

	public function add_css ( $fname, $id = "", $media = "", $ie = null, $skip_cache = false )
	{
		if ( $skip_cache || $ie )
			$this->_css_nocache [] = array ( "fname" => $fname, "id" => $id, "media" => $media, "ie" => $ie );
		else
			$this->_css [] = array ( "fname" => $fname, "id" => $id, "media" => $media, "ie" => $ie );
	}
}

	
/*
	def add_js ( self, fname, skip_cache = False ):
		if skip_cache:
			dest = self._js_nocache
		else:
			dest = self._js

		if isinstance ( fname, list ):
			for fn in fname:
				dest [ fn ] = fn
		else:
			dest [ fname ] = fname

	def add_js_code ( self, txt, tail = 0 ):
		if not tail:
			self._js_code.append ( txt )
		else:
			self._js_code_tail.insert ( 0, txt )

	def links_refs ( self ):
		for lnk in self._links.values ():
			#lnk [ 'href' ] = self._resolve_ref ( lnk [ 'href' ] )
			res = [ "<link" ]
			for k, v in lnk.iteritems ():
				res.append ( '%s="%s"' % ( k, v ) )

			res.append ( "/>" )

			print ' '.join ( res )

	def css_refs ( self ):
		for css in self._css.values ():
			res = []

			for el in ( "id", "media" ):
				if css.get ( el ):
					res.append ( '%s="%s"' % ( el, css [ el ] ) )

			print '<link rel="stylesheet" href="%s#%s" type="text/css" %s/>' % ( css [ 'fname' ], self._site_version, ' '.join ( res ) )

		for css in self._css_nocache.values ():
			prefix = ''
			suffix = ''
			res = []

			for el in ( "id", "media" ):
				if css.get ( el ):
					res.append ( '%s="%s"' % ( el, css [ el ] ) )

			if css.get ( "ie" ):
				prefix = "<!--[if %s]>" % css [ 'ie' ]
				suffix = "<![endif]-->"

			print '%s<link rel="stylesheet" href="%s#%s" type="text/css" %s/>%s' % ( prefix, css [ 'fname' ], self._site_version, ' '.join ( res ), suffix )


	def js_refs ( self ):
		cache_name = ''

		if self._cache_dir:
			cache_name = self._create_cache ()

		if not cache_name:
			for js in self._js.values ():
				print '<script type="text/javascript" src="%s#%s"></script>' % ( js, self._site_version )
		else:
			print '<script type="text/javascript" src="%s#%s"></script>' % ( cache_name, self._site_version )

		for js in self._js_nocache.values ():
			print '<script type="text/javascript" src="%s#%s"></script>' % ( js, self._site_version )

	def render_page ( self, html ):
		if self._has_redir: return

		#self._chrome_frame ()

		tit = "%s %s %s" % ( self.liwe.cfg.get ( "TITLE_PREPEND", "" ), self.title, self.liwe.cfg.get ( "TITLE_APPEND", "" ) )

		print self.html_modes [ self.html_mode ] % { "lang" : self.lang }
		print "<head><title>%s</title>" % tit
		self.dump_metas ()
		self.links_refs ()
		self.css_refs ()
		self.js_refs ()
		has_init = self._dump_layman_js ()
		print "</head><body"
		if has_init: print ' onload="layman_init()"'
		if self._body_classes: print ' class="%s"' % ' '.join ( self._body_classes )
		print ">"
		
		print html
		print "</body></html>"

	def add_body_class ( self, _class ):
		self._body_classes.append ( _class )

	def _chrome_frame ( self ):
		if int ( self.liwe.cfg.get ( "USE_CHROME_FRAME", 0 ) ) and self.liwe.env.get ( "HTTP_USER_AGENT", "X" ).find ( "MSIE" ) != -1:
			import parts
			self.liwe.pyhp.set_header ( 'X-UA-Compatible', 'chrome=1' )
			self.add_js ( 'http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js' )
			parts.add ( self, "ext" )
			parts.add_wwl ( self, "chromeframe" )
			self.add_js_code ( 'chromeframe.init()' )

	def _dump_layman_js ( self ):
		print '<script type="text/javascript" language="JavaScript">'
		print 'liwe.AJAX.url = "/ajax.pyhp";'

		has_init = False

		if self._js_code or self._js_code_tail:
			print 'function layman_init () {'
			for line in self._js_code:
				print line

			for line in self._js_code_tail:
				print line

			print '}'
			has_init = True

		print '</script>'

		return has_init


	def _create_cache ( self, ext = '.js' ):
		cache_name = md5crypt ( '-'.join ( self._js ) ) + ext

		full_name = os.path.join ( self._cache_dir, cache_name )
		if os.path.isfile ( full_name ):
			return full_name

		try:
			fout = file ( full_name, "w" )

			for f in self._js:
				if f [ 0 ] == '/': f = f [ 1 : ]

				f = f.replace ( ".js", ".comp.js" )

				try:
					fout.write ( file ( f ).read () )
				except:
					try:
						f = f.replace ( ".comp.js", ".js" )
						fout.write ( file ( f ).read () )
					except:
						sys.stderr.write ( "ERROR: could not read: %s\n" % f )

			fout.close ()

			return full_name
		except:
			# raise
			return ''

	# {{{ load_page ( page_name, block_name = False )
	def load_page ( self, page_name, block_name = False ):
		fname = os.path.join ( self._page_dir, page_name + ".html" )

		if os.path.isfile ( fname ):
			txt = open ( fname ).read ()
			txt = self._apply_regex ( txt, block_name )
		else:
			txt = "Page not found: %s" % fname

		return self._parse_data ( txt )
	# }}}
	# {{{ execute ( command )
	def execute ( self, command, kargs ):
		cmd = "%s.%s" % ( command [ 0 ], command [ 1 ] )
		res = self.liwe.invoke ( cmd, * command [ 2 : ], ** kargs )
		if '_txt' in res:
			txt = res [ '_txt' ]
		else:
			txt = "Layout Manager: Error invoking: %s (%s / %s)" % ( cmd, self.liwe.err_code, self.liwe.err_descr )
	
		return txt
	# }}}

	# {{{ _parse_data ( txt )
	def _parse_data ( self, txt ):
		def _remap ( txt ):
			return self.liwe.pyhp.session.data.get ( txt [ 1 : ], txt )

		res = ''
		start_pos = 0

		x = txt.find ( "<?fab" )
		while x != -1:
			res += txt [ start_pos : x ]
			start_pos = x + 5

			x = txt.find ( "?>", start_pos )
			if x == -1:
				sys.stderr.write ( "ERROR: missing end tag in template. Last valid pos: %d" % start_pos )
				break

			sub = txt [ start_pos : x ]
			cmds, kargs = args_parser.parse ( sub, _remap )
			res += str ( self.execute ( cmds, kargs ) )

			start_pos = x + 2
			x = txt.find ( "<?fab", start_pos )

		res += txt [ start_pos : ]

		return res
	# }}}
	# {{{ _split_command ( txt )
	def _split_command ( self, txt ):
		spl = [ self._unquote ( x ) for x in self._re_commands.split ( txt ) if x  ]
		return spl
	# }}}
	# {{{ _unquote ( x )
	def _unquote ( self, x ):
		if x [ 0 ] in ( "'", '"' ):
			return x [ 1 : -1 ]
		return x
	# }}}



	# {{{ _apply_regex ( txt, block_name )
	def _apply_regex ( self, txt, block_name ):
		txt = self._re_spaces.sub ( " ", txt )
		txt = self._re_body.sub ( "\\1", txt )

		if block_name:
			if txt.find ( "{" + "{{ BLK: %s" % block_name ) == -1:
				return '<strong style="color: red">Could not find: %s</strong>' % block_name

			regexp = re.compile ( ".*<!-- {{{ BLK: %s -->(.*)<!-- }}} %s -->(.*)$" % ( block_name, block_name ) )
			txt = regexp.sub ( "\\1", txt )

		txt = self._re_rep.sub ( "\\2", txt )
		txt = self._re_comments.sub ( "", txt )

		return txt.strip ()
	# }}}
}
*/